package com.gitee.lougnib.simplekits.quick_generator.sproject.importer.easypoi;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.gitee.lougnib.simplekits.quick_generator.common.constants.ComponentType;
import com.gitee.lougnib.simplekits.quick_generator.common.constants.ScreenLayoutRow;
import com.gitee.lougnib.simplekits.quick_generator.common.dto.screen.BaseComponentDto;
import com.gitee.lougnib.simplekits.quick_generator.common.dto.screen.ScreenComponentDto;
import com.gitee.lougnib.simplekits.quick_generator.common.dto.screen.ScreenDto;
import com.gitee.lougnib.simplekits.quick_generator.common.template.tools.AngularTool;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import lombok.extern.slf4j.Slf4j;

/**
 * 画面项目导入Service。
 *
 * - 每一个组件都要存放到画面组件中，组成一层结构，方便TS/Java等代码的生成。 -
 * - 每一个组件也都要存放到其父类组件中，组成分层结构，方便HTML等代码的生成。
 * TODO 表的标题支持2层结构
 *
 * @author LOU
 */
@Slf4j
public class EasypoiScreenImportService {

	private AngularTool angular = new AngularTool();

	public List<ScreenDto> parseFile(String filePath) {
		File file = new File(filePath);
		List<EasypoiScreenDto> importedScreenList = importScreen(file);
		List<EasypoiScreenItemDto> importedScreenItemList = importScreenItem(file);

		List<ScreenDto> screenList = new ArrayList<>();
		ScreenDto lastScreen = null;
		BaseComponentDto lastArea = null;
		BaseComponentDto lastRow = null;
		BaseComponentDto lastColumn = null;
		for (EasypoiScreenItemDto screenItem : importedScreenItemList) {

			// 开始新的画面
			String layoutRow = EasypoiKit.toValue(screenItem.getLayoutRow());
			if (lastScreen == null || (StringUtils.isNotBlank(screenItem.getScreenCode())
					&& !StringUtils.equalsIgnoreCase(lastScreen.getCode(), screenItem.getScreenCode()))) {
				lastScreen = newScreen(screenItem.getScreenCode(), importedScreenList);

				lastArea = newArea(lastScreen, screenItem);
				lastScreen.addChildComponent(lastArea);

				if (ScreenLayoutRow.NEW_TABLE.equalsValue(layoutRow)) {
					lastRow = newTable(lastScreen, screenItem);
				} else {
					lastRow = newGridRow(lastScreen, screenItem);
				}
				lastArea.addChildComponent(lastRow);

				screenList.add(lastScreen);
			} else if (ScreenLayoutRow.NEW_AREA.equalsValue(layoutRow)) {
				lastArea = newArea(lastScreen, screenItem);
				lastScreen.addChildComponent(lastArea);

				lastRow = newGridRow(lastScreen, screenItem);
				lastArea.addChildComponent(lastRow);
			} else if (ScreenLayoutRow.NEW_TABLE.equalsValue(layoutRow)) {
				lastRow = newTable(lastScreen, screenItem);
				lastArea.addChildComponent(lastRow);

				// 如果是表格的定义，继续下一行的处理
				if (ComponentType.TABLE.equalsValue(screenItem.getComponentType())) {
					continue;
				}
			} else if (ScreenLayoutRow.NEW_ROW.equalsValue(layoutRow)) {
				lastRow = newGridRow(lastScreen, screenItem);
				lastArea.addChildComponent(lastRow);
			}

			BaseComponentDto component = null;
			if (StringUtils.isNotBlank(screenItem.getComponentName1())) {
				component = newComponentL1(lastScreen, screenItem);
				lastRow.addChildComponent(component);
			} else if (StringUtils.isNotBlank(screenItem.getComponentName2())) {
				component = newComponentL2(lastScreen, screenItem);
				if (lastColumn != null) {
					lastColumn.addChildComponent(component);
				}
			}

			if (angular.isTableColumn(component)) {
				lastColumn = component;
			}
		}

		return screenList;
	}

	private ScreenDto newScreen(String screenCode, List<EasypoiScreenDto> importedScreenList) {
		ScreenDto screen = new ScreenDto();
		screen.setCode(screenCode);
		for (EasypoiScreenDto importedScreen : importedScreenList) {
			if (StringUtils.equalsIgnoreCase(screenCode, importedScreen.getScreenCode())) {
				screen.setName(importedScreen.getScreenName());
				screen.setComment(importedScreen.getScreenComment());
				break;
			}
		}
		return screen;
	}

	private BaseComponentDto newArea(ScreenDto lastScreen, EasypoiScreenItemDto screenItem) {
		ScreenComponentDto component = new ScreenComponentDto();

		lastScreen.addComponentToAll(component);

		if (StringUtils.isBlank(screenItem.getComponentType())
				|| ComponentType.CARD.equalsValue(screenItem.getComponentType())) {
			component.setCode(screenItem.getComponentCode());
			component.setName(screenItem.getComponentName1());
			component.setComment(screenItem.getComment());
		}
		component.setComponentType(ComponentType.CARD.getValue());
		return component;
	}

	private BaseComponentDto newGridRow(ScreenDto lastScreen, EasypoiScreenItemDto screenItem) {
		ScreenComponentDto component = new ScreenComponentDto();

		lastScreen.addComponentToAll(component);

		component.setCode(screenItem.getComponentCode());
		component.setName(screenItem.getComponentName1());
		component.setComment(screenItem.getComment());
		component.setComponentType(ComponentType.GRID_ROW.getValue());
		return component;
	}

	private BaseComponentDto newTable(ScreenDto lastScreen, EasypoiScreenItemDto screenItem) {
		ScreenComponentDto component = new ScreenComponentDto();

		lastScreen.addComponentToAll(component);

		component.setCode(screenItem.getComponentCode());
		component.setName(screenItem.getComponentName1());
		component.setComment(screenItem.getComment());
		component.setComponentType(ComponentType.TABLE.getValue());
		return component;
	}

	private BaseComponentDto newComponentL1(ScreenDto lastScreen, EasypoiScreenItemDto screenItem) {
		BaseComponentDto component = newComponent(lastScreen, screenItem);
		component.setName(screenItem.getComponentName1());
		return component;
	}

	private BaseComponentDto newComponentL2(ScreenDto lastScreen, EasypoiScreenItemDto screenItem) {
		BaseComponentDto component = newComponent(lastScreen, screenItem);
		component.setName(screenItem.getComponentName2());
		return component;
	}

	private BaseComponentDto newComponent(ScreenDto lastScreen, EasypoiScreenItemDto screenItem) {
		ScreenComponentDto component = new ScreenComponentDto();
		lastScreen.addComponentToAll(component);
		component.setCode(screenItem.getComponentCode());
		component.setName(screenItem.getComponentName1());
		component.setComponentType(screenItem.getComponentType());
		if (StringUtils.isNotBlank(screenItem.getMaxLength())) {
			component.setMaxLength(Integer.getInteger(screenItem.getMaxLength()));
		}
		component.setComment(screenItem.getComment());
		return component;
	}

	@SuppressWarnings("deprecation")
	private List<EasypoiScreenDto> importScreen(File file) {
		ImportParams params = new ImportParams();
		params.setTitleRows(0);
		params.setHeadRows(1);
		params.setStartSheetIndex(0);
		params.setSheetNum(1);
		// 必须确保第一列有值，否则导入不进来
		params.setKeyIndex(0); // 20190725：虽然是不推荐使用的方法，但还在起作用
		return ExcelImportUtil.importExcel(file, EasypoiScreenDto.class, params);
	}

	@SuppressWarnings("deprecation")
	private List<EasypoiScreenItemDto> importScreenItem(File file) {
		ImportParams params = new ImportParams();
		params.setTitleRows(1);
		params.setHeadRows(1);
		params.setStartSheetIndex(1);
		params.setSheetNum(1);
		// 必须确保第一列有值，否则导入不进来
		params.setKeyIndex(0);
		return ExcelImportUtil.importExcel(file, EasypoiScreenItemDto.class, params);
	}
}
